package com.cdks.wuxiu.api.util;

import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
import com.cdks.wuxiu.api.model.dto.CloudStorageDTO;
import com.cdks.wuxiu.common.component.constant.ApiCodeEnum;
import com.cdks.wuxiu.common.exception.ApiException;

import lombok.extern.slf4j.Slf4j;

import java.time.Instant;
import java.util.ArrayList;
import java.util.List;

/**
 * 阿里云存储工具类
 */
@Slf4j
public class AliyunOSSUtils {
    /**
     * 访问密钥 ID
     */
    private static final String ACCESS_KEY_ID = "LTAI4GJbzR1oQfL668RFVB42";
    /**
     * 访问密钥 SECRET
     */
    private static final String ACCESS_KEY_SECRET = "pbSpwy5DjqM6FAdDcj7R1W47QQ8Okg";
    /**
     * 指定角色的ARN
     */
    private static final String ROLE_ARN = "acs:ram::1132581043208955:role/aliyunossfullaccess";
    /**
     * 用户自定义参数，此参数用来区分不同的令牌 CLIENT
     */
    private static final String CLIENT_ROLE_SESSION_NAME = "modui-client@1132581043208955.onaliyun.com";
    /**
     * 用户自定义参数，此参数用来区分不同的令牌 SERVER
     */
    private static final String SERVER_ROLE_SESSION_NAME = "modui-server@1132581043208955.onaliyun.com";
    /**
     * 接入地址
     */
    private static final String REGION_ID = "cn-hangzhou";

    /**
     * 获取临时授权
     */
    public static CloudStorageDTO getAuthData() {
        //构建一个阿里云客户端，用于发起请求
        //构建阿里云客户端时需要设置AccessKey ID和AccessKey Secret
        DefaultProfile profile = DefaultProfile.getProfile(REGION_ID, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        IAcsClient client = new DefaultAcsClient(profile);
        //构造请求，设置参数
        AssumeRoleRequest request = new AssumeRoleRequest();
        request.setRoleArn(ROLE_ARN);
        request.setRoleSessionName(SERVER_ROLE_SESSION_NAME);
        request.setDurationSeconds(900L);
        //发起请求，并得到响应
        CloudStorageDTO ossData = new CloudStorageDTO();

        try {
            AssumeRoleResponse response = client.getAcsResponse(request);
            AssumeRoleResponse.Credentials credentials = response.getCredentials();
            long expiration = Instant.parse(credentials.getExpiration()).getEpochSecond();

            ossData.setAccessKeyId(credentials.getAccessKeyId());
            ossData.setAccessKeySecret(credentials.getAccessKeySecret());
            ossData.setSecurityToken(credentials.getSecurityToken());
            ossData.setExpiration(expiration);
            ossData.setStatusCode(200);
        } catch (ClientException e) {
            //发送短信通知
            SmsUtils.sendManageNotice("获取云存授权失败");

            log.error("获取云存授权失败", e);
            throw new ApiException(ApiCodeEnum.SERVICE_ERROR.getCode(), "获取云存授权失败");
        }

        return ossData;
    }

    public static void deleteObject(String endpoint, String bucketName, String objectName) {
        // 创建ClientConfiguration实例，您可以按照实际情况修改默认参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 设置是否支持CNAME。CNAME是指将自定义域名绑定到存储空间上。
        conf.setSupportCname(true);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
        // 删除文件。如需删除文件夹，请将ObjectName设置为对应的文件夹名称。如果文件夹非空，则需要将文件夹下的所有object删除后才能删除该文件夹。
        ossClient.deleteObject(bucketName, objectName);
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    public static void deleteList(String endpoint, String bucketName, String prefix) {
        // 创建ClientConfiguration实例，您可以按照实际情况修改默认参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 设置是否支持CNAME。CNAME是指将自定义域名绑定到存储空间上。
        conf.setSupportCname(true);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
        // 列举所有包含指定前缀的文件并删除。
        String nextMarker = null;
        ObjectListing objectListing = null;

        do {
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName)
                    .withPrefix(prefix)
                    .withMarker(nextMarker);

            objectListing = ossClient.listObjects(listObjectsRequest);
            if (objectListing.getObjectSummaries().size() > 0) {
                List<String> keys = new ArrayList<>();
                for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
                    keys.add(s.getKey());
                }
                DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName).withKeys(keys);
                ossClient.deleteObjects(deleteObjectsRequest);
            }
            nextMarker = objectListing.getNextMarker();
        } while (objectListing.isTruncated());

        // 关闭OSSClient。
        ossClient.shutdown();
    }

    public static void copyObject(String endpoint, String bucketName, String sourceKey, String destinationKey) {
        // 创建ClientConfiguration实例，您可以按照实际情况修改默认参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 设置是否支持CNAME。CNAME是指将自定义域名绑定到存储空间上。
        conf.setSupportCname(true);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
        // 拷贝文件。
        CopyObjectResult result = ossClient.copyObject(bucketName, sourceKey, bucketName, destinationKey);
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    public static void copyList(String endpoint, String bucketName, String sourcePrefix, String destinationPrefix) {
        // 创建ClientConfiguration实例，您可以按照实际情况修改默认参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 设置是否支持CNAME。CNAME是指将自定义域名绑定到存储空间上。
        conf.setSupportCname(true);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
        // 列举所有包含指定前缀的文件。
        String nextMarker = null;
        ObjectListing objectListing = null;

        do {
            ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName)
                    .withPrefix(sourcePrefix)
                    .withMarker(nextMarker);

            objectListing = ossClient.listObjects(listObjectsRequest);
            if (objectListing.getObjectSummaries().size() > 0) {
                for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
                    String key = StrUtil.removePrefix(s.getKey(), sourcePrefix);
                    copyObject(endpoint, bucketName, s.getKey(), destinationPrefix + key);
                }
            }
            nextMarker = objectListing.getNextMarker();
        } while (objectListing.isTruncated());
        
        // 关闭OSSClient。
        ossClient.shutdown();
    }

    public static void renameObject(String endpoint, String bucketName, String sourceKey, String destinationKey) {
        // 创建ClientConfiguration实例，您可以按照实际情况修改默认参数。
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 设置是否支持CNAME。CNAME是指将自定义域名绑定到存储空间上。
        conf.setSupportCname(true);
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET, conf);
        // 拷贝文件。
        CopyObjectResult result = ossClient.copyObject(bucketName, sourceKey, bucketName, destinationKey);
        // 删除文件
        ossClient.deleteObject(bucketName, sourceKey);
        // 关闭OSSClient。
        ossClient.shutdown();
    }
}
